﻿using System;
using System.Threading;
using OmegaBot;

namespace drone_cc
{
    public class droneRogueCombat : CombatClass
    {
        //TODO:

        #region properties / class setup
        //combat abilities
        SpellKeyDefinition stealth;
        SpellKeyDefinition ambush;
        SpellKeyDefinition cheapshot;
        SpellKeyDefinition garrote;
        SpellKeyDefinition mutilate;
        SpellKeyDefinition sinisterstrike;
        SpellKeyDefinition envenom;
        SpellKeyDefinition eviscerate;
        SpellKeyDefinition kidneyshot;
        SpellKeyDefinition rupture;
        SpellKeyDefinition sliceanddice;
        SpellKeyDefinition kick;
        SpellKeyDefinition fanofknives;
        SpellKeyDefinition shoot;
        SpellKeyDefinition riposte;


        //emergency spells
        SpellKeyDefinition evasion;
        SpellKeyDefinition vanish;
        SpellKeyDefinition healthpotion;
        SpellKeyDefinition thistletea;
        SpellKeyDefinition bandage;

        //combat buffs
        SpellKeyDefinition adrenalinerush;
        SpellKeyDefinition killingspree;
        SpellKeyDefinition bladeflurry;
        SpellKeyDefinition coldblood;

        //poisons
        SpellKeyDefinition anestheticpoison;
        SpellKeyDefinition cripplingpoison;
        SpellKeyDefinition deadlypoison;
        SpellKeyDefinition instantpoison;
        SpellKeyDefinition mindnumbingpoison;
        SpellKeyDefinition woundpoision;

        public IniManager Ini;

        public override string CombatClassName { get { return "drone-cc rogue"; } }

        public override void CreateSetup()
        {
            Ini = new IniManager("drone-cc.ini");
            Ini.SetComment("drone-cc.ini\r\n\r\nconfiguration for drone-cc");

            //combat spells
            Ini.Set("rogue", "usemutilate", "true");
            Ini.Set("rogue", "usestealth", "true");
            Ini.Set("rogue", "usekick", "true");
            Ini.Set("rogue", "userangedpull", "false");
            Ini.Set("rogue", "useopener", "true");
            Ini.Set("rogue", "usespam", "true");
            Ini.Set("rogue", "usefinisher1", "true");
            Ini.Set("rogue", "usefinisher2", "true");

            Ini.Set("rogue", "opener", "Garrote");
            Ini.Set("rogue", "spam", "Mutilate");
            Ini.Set("rogue", "finisher1", "Slice And Dice");
            Ini.Set("rogue", "finisher2", "Envenom");
            Ini.Set("rogue", "finisher1at", "3");
            Ini.Set("rogue", "finisher2at", "4");

            Ini.Set("rogue", "usemount", "false");
            Ini.Set("rogue", "skiplootcheck", "false");
            Ini.Set("rogue", "mountdistance", "30");

            Ini.Set("rogue", "combineitems", "false");
            Ini.Set("rogue", "openclams", "false");
            Ini.Set("rogue", "enablepvp", "false");
           
            Ini.Load();
            Ini.Save();
        }

        // Make our special setup window and return it so it can be shown:
        protected override ClassSetupPanel CreateSetupPanel()
        {
            return new droneRogueSetup(this);
        }

        protected override void SetupKeys()
        {
            Log.WriteLine("Drone is setting up spell keys");
            
            //combat abilities
            stealth = SpellKeys.CreateFromSpell("stealth", 1784);
            ambush = SpellKeys.CreateFromHostileSpell("ambush", 8676);
            cheapshot = SpellKeys.CreateFromHostileSpell("cheapshot", 1833);
            garrote = SpellKeys.CreateFromHostileSpell("garrote", 703);
            mutilate = SpellKeys.CreateFromHostileSpell("mutilate", 1329);
            sinisterstrike = SpellKeys.CreateFromHostileSpell("sinisterstrike", 1752);
            envenom = SpellKeys.CreateFromHostileSpell("envenom", 32645);
            eviscerate = SpellKeys.CreateFromHostileSpell("eviscerate", 2098);
            kidneyshot = SpellKeys.CreateFromHostileSpell("kidneyshot", 408);
            rupture = SpellKeys.CreateFromHostileSpell("rupture", 1943);
            sliceanddice = SpellKeys.CreateFromSpell("sliceanddice", "5171 6774");
            kick = SpellKeys.CreateFromHostileSpell("kick", 1766);
            fanofknives = SpellKeys.CreateFromHostileSpell("fanofknives", 51723);
            shoot = SpellKeys.CreateFromHostileSpell("shoot", "3018 2764");
            riposte = SpellKeys.CreateFromHostileSpell("riposte", 14251);

            //emergency spells
            evasion = SpellKeys.CreateFromSpell("evasion", "5277 26669");
            vanish = SpellKeys.CreateFromSpell("vanish", "1856 1857 26889");
            healthpotion = SpellKeys.CreateFromItems("healthpotion", "118 858 929 1710 3928 13446 22829 33447 41166");
            thistletea = SpellKeys.CreateFromItems("thistletea", "7676");
            bandage = SpellKeys.CreateFromItems("bandage", "1251 2581 3530 3531 6450 6451 14529 14530 21990 21991 34721 34722");

            //combat buffs
            adrenalinerush = SpellKeys.CreateFromSpell("adrenalinerush", 13750);
            killingspree = SpellKeys.CreateFromSpell("killingspree", 51690);
            bladeflurry = SpellKeys.CreateFromSpell("bladeflurry", 13877);
            coldblood = SpellKeys.CreateFromSpell("coldblood", 14177);

            //poisons
            anestheticpoison = SpellKeys.CreateFromItems("anestheticpoison", "21835 43237");
            cripplingpoison = SpellKeys.CreateFromItems("cripplingpoison", "3775 3776");
            deadlypoison = SpellKeys.CreateFromItems("deadlypoison", "2892 2893 8984 8985 20844 22053 22054 43232 43233");
            instantpoison = SpellKeys.CreateFromItems("instantpoison", "6947 6949 6950 8926 8927 8928 21927 43230 43231");
            mindnumbingpoison = SpellKeys.CreateFromItems("mindnumbingpoison", "5237 6951 9186");
            woundpoision = SpellKeys.CreateFromItems("woundpoision", "10918 10920 10921 10922 22055 43234 43235");

            //mounts
            DroneCombatClassUtilties.setupMountSpellKeys(SpellKeys);

            // Set up normal options for these spells:
            mutilate.SetDefaultOptions(CastOptions.ChainCast);
            sinisterstrike.SetDefaultOptions(CastOptions.ChainCast);
            anestheticpoison.SetDefaultOptions(CastOptions.ExpectCastBar);
            cripplingpoison.SetDefaultOptions(CastOptions.ExpectCastBar);
            deadlypoison.SetDefaultOptions(CastOptions.ExpectCastBar);
            instantpoison.SetDefaultOptions(CastOptions.ExpectCastBar);
            mindnumbingpoison.SetDefaultOptions(CastOptions.ExpectCastBar);
            woundpoision.SetDefaultOptions(CastOptions.ExpectCastBar);

        }
        #endregion

        #region Resting / Healing / Buffs
        public static bool poisonAppliedMH()
        {
            if (GameItem.GetEquippedItem("MainHandSlot").HasTempEnchant)
            {
                return true;
            }
            return false;
        }

        public static bool poisonAppliedOH()
        {
            if (GameItem.GetEquippedItem("SecondaryHandSlot").HasTempEnchant)
            {
                return true;
            }
            return false;
        }

        public static void applyPoisonMH(SpellKeyDefinition thePoison)
        {
            if (thePoison.canCast())
            {
                thePoison.Cast(CastOptions.None);
                if (thePoison.IsFiring)
                {
                    Log.WriteLine("Poisoning Mainhand: {0} with {1}", GameItem.GetEquippedItem("MainHandSlot").Name, thePoison.KeyName);
                    if (InterfaceItem.FindByName("CharacterFrame").Visible)
                    {
                        InterfaceItem.FindByName("CharacterMainHandSlot").Click(false);
                    }
                    else
                    {
                        InterfaceItem.FindByName("CharacterMicroButton").Click(false);
                        InterfaceItem.FindByName("CharacterMainHandSlot").Click(false);
                    }
                    InterfaceItem.FindByName("CharacterMicroButton").Click(false);
                }
            }
        }

        public static void applyPoisonOH(SpellKeyDefinition thePoison)
        {
            if (thePoison.canCast())
            {
                thePoison.Cast(CastOptions.None);
                if (thePoison.IsFiring)
                {
                    Log.WriteLine("Poisoning Offhand: {0} with {1}", GameItem.GetEquippedItem("SecondaryHandSlot").Name, thePoison.KeyName);
                    if (InterfaceItem.FindByName("CharacterFrame").Visible)
                    {
                        InterfaceItem.FindByName("CharacterSecondaryHandSlot").Click(false);

                    }
                    else
                    {
                        InterfaceItem.FindByName("CharacterMicroButton").Click(false);
                        InterfaceItem.FindByName("CharacterSecondaryHandSlot").Click(false);
                    }
                    InterfaceItem.FindByName("CharacterMicroButton").Click(false);
                }
            }
        }

        public override bool CanDrink
        {
            get
            {
                return false;
            }
        }

        public override bool DoLightHeal()
        {
            return false;

        }

        public override bool DoBigHeal()
        {
            return false;

        }

        public override void Buff()
        {
            //Item Combine
            if (DroneCombatClassUtilties.needCombine() &&
                Ini.GetBoolean("rogue", "combineitems", false))
            {
                DroneCombatClassUtilties.combineItems(this.Input);
            }

            //open clams
            if (DroneCombatClassUtilties.needOpenClams() &&
                Ini.GetBoolean("rogue", "openclams", false))
            {
                DroneCombatClassUtilties.combineItems(this.Input);
            }

            //mount section
            if (!Me.isMounted() &&
                Ini.GetBoolean("rogue", "usemount", false))
            {
                if (Me.mustMount(Ini, "rogue"))
                {
                    Me.mountUp(this.Input);
                }
            }

            //poisoning weapons
            if (!poisonAppliedMH() &&
                Ini.GetBoolean("rogue", "usemhpoison", false))
            {
                switch (Ini.GetString("rogue", "mhpoison"))
                {
                    case "Anesthetic Poison":
                        applyPoisonMH(anestheticpoison);
                        break;
                    case "Crippling Poison":
                        applyPoisonMH(cripplingpoison);
                        break;
                    case "Deadly Poison":
                        applyPoisonMH(deadlypoison);
                        break;
                    case "Instant Poison":
                        applyPoisonMH(instantpoison);
                        break;
                    case "Mind-numbing Poison":
                        applyPoisonMH(mindnumbingpoison);
                        break;
                    case "Wound Poison":
                        applyPoisonMH(woundpoision);
                        break;
                    default:
                        applyPoisonMH(instantpoison);
                        break;
                }
            }
            if (!poisonAppliedOH() &&
                Ini.GetBoolean("rogue", "useohpoison", false))
            {
                switch (Ini.GetString("rogue", "ohpoison"))
                {
                    case "Anesthetic Poison":
                        applyPoisonOH(anestheticpoison);
                        break;
                    case "Crippling Poison":
                        applyPoisonOH(cripplingpoison);
                        break;
                    case "Deadly Poison":
                        applyPoisonOH(deadlypoison);
                        break;
                    case "Instant Poison":
                        applyPoisonOH(instantpoison);
                        break;
                    case "Mind-numbing Poison":
                        applyPoisonOH(mindnumbingpoison);
                        break;
                    case "Wound Poison":
                        applyPoisonOH(woundpoision);
                        break;
                    default:
                        applyPoisonOH(deadlypoison);
                        break;
                }
            }

        }


        #endregion

        #region Combat
        protected override CombatResult Combat(GameUnit Target)
        {
            bool toggle = true;

            if (Me.isMounted())
            {
                Me.dismount();
                Input.ReleaseAllKeys();
            }

            if (!Target.IsMob && !Ini.GetBoolean("rogue", "enablepvp", false))
            {
                Log.WriteLine("Attempted to Target player on accident!");
                return CombatResult.Retry;
            }
            //Stealth
            if (Ini.GetBoolean("rogue", "usestealth", false) &&
                stealth.canCast())
            {
                Target.GoTo(23, true);
                stealth.Cast(CastOptions.FastReturn);
            }
            //End Stealth

            // Close Distance before Combat
            if (Ini.GetBoolean("rogue", "userangedpull", true))
            {
                if (Target.Distance > 5 && Target.TargetGUID == 0)
                {
                    if (Target.Distance > 28)
                    {
                        Target.GoTo(28, false);
                    }
                    if (shoot.canCast())
                    {
                        shoot.Cast(CastOptions.ExpectCastBar);
                    }
                    Target.GoTo();
                }
            }
            Target.Face();
            Target.GoTo();
            Input.ReleaseAllKeys();
            //End Close Distance Before Combat

            //Opener
            if (Me.IsStealth)
            {
                string opener = Ini.GetString("rogue", "opener");
                switch (opener)
                {
                    case "Ambush":
                        Target.AdjustForMelee(false);
                        Input.ReleaseAllKeys();
                        if (ambush.canCast() && Target.IsFacingAway)
                        {

                            ambush.Cast(CastOptions.FastReturn);
                        }
                        else
                        {
                            if (cheapshot.canCast())
                            {
                                cheapshot.Cast(CastOptions.FastReturn);
                            }
                        }
                        break;
                    case "Cheap Shot":
                        Target.AdjustForMelee(false);
                        Input.ReleaseAllKeys();
                        if (cheapshot.canCast())
                        {
                            cheapshot.Cast(CastOptions.FastReturn);
                        }
                        break;
                    case "Garrote":
                        Target.AdjustForMelee(false);
                        Input.ReleaseAllKeys();
                        if (garrote.canCast() && Target.IsFacingAway)
                        {
                            garrote.Cast(CastOptions.FastReturn);
                        }
                        break;
                    default:
                        Target.AdjustForMelee(false);
                        Input.ReleaseAllKeys();
                        if (cheapshot.canCast())
                        {
                            cheapshot.Cast(CastOptions.FastReturn);
                        }
                        break;
                }
            }
            //End Opener


            // Main loop!
            while (true)
            {
                GameUnit extra = GameUnit.GetNearestAttacker(Target.GUID);
                CombatResult result = CheckCommonCombatResult(Target, false);

                Thread.Sleep(107);
                if (result != CombatResult.Unknown)
                {
                    return result;
                }

                // Adjust Ourselves
                if (Target.Distance > 5.0)
                {
                    Target.GoTo();
                    Input.ReleaseAllKeys();
                    continue;
                }
                else
                {
                    Target.Face();
                    Target.AdjustForMelee(true);
                    Input.ReleaseAllKeys();
                }
                // End Adjust

                //Healing Code
                if ((Me.Health < .80 && extra != null) || (Me.Health < .50))
                {
                    if (evasion.canCast())
                    {
                        evasion.Cast(CastOptions.FastReturn);
                        continue;
                    }

                }
                if (Me.Health < .15 ||
                   (Me.Health < .30 && extra != null))
                {
                    if (vanish.canCast())
                    {
                        vanish.Cast(CastOptions.FastReturn);
                        continue;
                    }
                }//End Healing Code

                //interupt w/ kick
                if (Target.IsCasting && Ini.GetBoolean("rogue", "usekick", false))
                {
                    if (kick.canCast())
                    {
                        kick.Cast();
                        continue;
                    }
                }

                //riposte on parry
                if (riposte.canCast())
                {
                    riposte.Cast();
                    continue;
                }

                //DPS PUMP
                if (NeedMoreDPS)
                {
                    //Adrenaline Rush, Killing Spree, Blade Flurry, Cold Blood
                    if (adrenalinerush.canCast())
                    {
                        adrenalinerush.Cast(CastOptions.FastReturn);
                        continue;
                    }
                    if (bladeflurry.canCast() && extra != null)
                    {
                        bladeflurry.Cast(CastOptions.FastReturn);
                        continue;
                    }
                    if (killingspree.canCast())
                    {
                        //Killing Spree + Adrenaline Rush is stupid.
                        Buff[] buffs = Me.GetUnitBuffs();
                        bool bufffound = false;
                        foreach (Buff v in buffs)
                        {
                            //check for adrenaline rush
                            if (v.SpellID == 13750)
                            {
                                bufffound = true;
                            }
                        }
                        if (!bufffound)
                        {
                            killingspree.Cast(CastOptions.FastReturn);
                            continue;
                        }
                    }
                    if (coldblood.canCast())
                    {
                        coldblood.Cast(CastOptions.FastReturn);
                        continue;
                    }
                }//End DPS Pump

                //Rotation
                //spammer
                if (Ini.GetBoolean("rogue", "usespam", false))
                {

                    string spammer = Ini.GetString("rogue", "spam");
                    switch (spammer)
                    {
                        case "Sinister Strike":
                            if (sinisterstrike.canCast())
                            {
                                sinisterstrike.Cast();
                                continue;
                            }
                            break;
                        case "Mutilate":
                            if (mutilate.canCast())
                            {
                                mutilate.Cast();
                                continue;
                            }
                            break;
                        default:
                            if (sinisterstrike.canCast())
                            {
                                sinisterstrike.Cast();
                                continue;
                            }
                            break;
                    }
                }//end spammer

                //finisher
                if (Ini.GetBoolean("rogue", "usefinisher1", false) ||
                    Ini.GetBoolean("rogue", "usefinisher2", false))
                {
                    string finisher1 = Ini.GetString("rogue", "finisher1");
                    string finisher2 = Ini.GetString("rogue", "finisher2");

                    if (toggle && Me.ComboPoints >= Convert.ToInt32(Ini.GetString("rogue", "finisher1at")))
                    {
                        switch (finisher1)
                        {
                            case "Envenom":
                                if (envenom.canCast())
                                {
                                    envenom.Cast(CastOptions.FastReturn);
                                    toggle = false;
                                }
                                break;
                            case "Eviscerate":
                                if (eviscerate.canCast())
                                {
                                    eviscerate.Cast(CastOptions.FastReturn);
                                    toggle = false;
                                }
                                break;
                            case "Kidney Shot":
                                if (kidneyshot.canCast())
                                {
                                    kidneyshot.Cast(CastOptions.FastReturn);
                                    toggle = false;
                                }
                                break;
                            case "Rupture":
                                if (rupture.canCast())
                                {
                                    rupture.Cast(CastOptions.FastReturn);
                                    toggle = false;
                                }
                                break;
                            case "Slice and Dice":
                                if (sliceanddice.canCast())
                                {
                                    sliceanddice.Cast(CastOptions.FastReturn);
                                    toggle = false;
                                }
                                break;
                            default:
                                break;
                        }
                        continue;
                    }
                    else if (!toggle && Me.ComboPoints >= Convert.ToInt32(Ini.GetString("rogue", "finisher2at")))
                    {
                        switch (finisher2)
                        {
                            case "Envenom":
                                if (envenom.canCast())
                                {
                                    envenom.Cast(CastOptions.FastReturn);
                                    toggle = true;
                                }
                                break;
                            case "Eviscerate":
                                if (eviscerate.canCast())
                                {
                                    eviscerate.Cast(CastOptions.FastReturn);
                                    toggle = true;
                                }
                                break;
                            case "Kidney Shot":
                                if (kidneyshot.canCast())
                                {
                                    kidneyshot.Cast(CastOptions.FastReturn);
                                    toggle = true;
                                }
                                break;
                            case "Rupture":
                                if (rupture.canCast())
                                {
                                    rupture.Cast(CastOptions.FastReturn);
                                    toggle = true;
                                }
                                break;
                            case "Slice and Dice":
                                if (sliceanddice.canCast())
                                {
                                    sliceanddice.Cast(CastOptions.FastReturn);
                                    toggle = true;
                                }
                                break;
                            default:
                                break;
                        }
                        continue;

                    }

                }//end finisher
                //end rotation
            }//End While
        }//End Combat
        #endregion
    }
}